/**
 * Copyright (c) 2014 by it's authors. 
 * All rights reserved. See COPYING, AUTHORS.
 * 
 * This file is part of DanceMania project; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License, Version 3.
 * 
 * DanceMania is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License,
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */
package com.m2dl.niptus.pathtrack.classes;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.hardware.Sensor;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import com.m2dl.niptus.pathtrack.R;
import com.m2dl.niptus.pathtrack.db.DBAdapter;
import com.m2dl.niptus.pathtrack.db.Location;
import com.m2dl.niptus.pathtrack.utils.Constants;

public class MapView extends View implements OnTouchListener {
	private final String TAG = Constants.TAG + "." + getClass().getSimpleName();

	private DBAdapter mDb;
	private List<Location> mPath = new ArrayList<Location>();
	
	class Point {
		float x = 0;
		float y = 0;
	}

	private Bitmap mThumbOn;
	private Bitmap mThumbOff;
	private Bitmap mHome;
	private boolean mBitmapResized = false;

	private Paint mThickPaint = new Paint();
	private Paint mThinPaint = new Paint();
	private Paint mPathPaint = new Paint();
	private Paint mReturnPaint = new Paint();

	// Custom width and height of the canvas according to display size
	private int mWidth;
	private int mHeight;
	
	private int mReturnId = -1;
	
	// Constructors
	public MapView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	public MapView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public MapView(Context context) {
		super(context);
		init(context);
	}
	
	private void init(Context context) {
		this.setOnTouchListener(this);
		
		Log.i(TAG, "MapView initialized");
		
		// Define paints
		mThickPaint.setColor(getResources().getColor(R.color.gray_normal));
		mThickPaint.setAntiAlias(true);
		mThickPaint.setStyle(Style.STROKE);
		mThickPaint.setStrokeWidth(2);

		mThinPaint.setColor(getResources().getColor(R.color.gray_dark));
		mThinPaint.setStyle(Style.STROKE);
		mThinPaint.setPathEffect(new DashPathEffect(new float[] { 4, 2 }, 0));
		mThinPaint.setStrokeWidth(1);
		
		mPathPaint.setColor(getResources().getColor(R.color.blue_normal));
		mPathPaint.setAntiAlias(true);
		mPathPaint.setStyle(Style.FILL_AND_STROKE);
		mPathPaint.setStrokeWidth(10);
		
		mReturnPaint.setColor(getResources().getColor(R.color.red_normal));
		mReturnPaint.setAntiAlias(true);
		mReturnPaint.setStyle(Style.FILL_AND_STROKE);
		mReturnPaint.setStrokeWidth(10);

		// Define bitmap of position circle
		mThumbOn = BitmapFactory.decodeResource(getResources(), R.drawable.marker_on);
		mThumbOff = BitmapFactory.decodeResource(getResources(), R.drawable.marker_off);
		mHome = BitmapFactory.decodeResource(getResources(), R.drawable.home_logo);
	}

	@Override
	public void onDraw(Canvas canvas) {
		// View sizes
		mHeight = getHeight();
		mWidth = getWidth();
		
		if (!mBitmapResized) {
			mThumbOn = Bitmap.createScaledBitmap(mThumbOn, mWidth / 10, (int) (mWidth * 1.57f / 10f), true);
			mThumbOff = Bitmap.createScaledBitmap(mThumbOff, mWidth / 10, (int) (mWidth * 1.57f / 10f), true);
			mHome = Bitmap.createScaledBitmap(mHome, (int) (mWidth * 1.22f / 10f), mWidth / 10, true);
			mBitmapResized = true;
		}
		
		// Grid drawing
		for (int i = 0; i < 5; i++) {
			if (i % 2 == 0) {
				canvas.drawLine(0, i * (mHeight / 4), mWidth, i * (mHeight / 4), mThickPaint);
				canvas.drawLine(i * (mWidth / 4), 0, i * (mWidth / 4), mHeight, mThickPaint);
			} else {
				canvas.drawLine(0, i * (mHeight / 4), mWidth, i * (mHeight / 4), mThinPaint);
				canvas.drawLine(i * (mWidth / 4), 0, i * (mWidth / 4), mHeight, mThinPaint);
			}
		}

		canvas.drawBitmap(mThumbOn, mWidth/2 - mThumbOn.getWidth()/2, mHeight/2 - mThumbOn.getHeight(), null);
		drawPath(canvas);
	}

	public boolean onTouch(View view, MotionEvent event) {
		invalidate();
		return true;
	}

	public void onAccuracyChanged(Sensor sensor, int accuracy) {}
	
	/** Path section **/
	class PathComparator implements Comparator<Location> {
	    @Override
	    public int compare(Location a, Location b) {
	        if (a.getId() < b.getId())
	        	return -1;
	        else if (a.getId() > b.getId())
	        	return 1;
	        else
	        	return 0;
	    }
	}
	
	public void onStep() {
		mPath.clear();
		
		mDb = new DBAdapter(getContext());
		mPath = mDb.getAllObjects();
		mDb.close();
		
		Log.e(TAG, "onStep: " + mPath.size());
		Collections.sort(mPath, new PathComparator());
		invalidate();
	}
	
	private void drawPath(Canvas canvas) {
		if (mPath.size() < 2)
			return;
		
		// Center the path
		Location last = mPath.get(mPath.size() - 1);
		
		float offsetX = Math.abs(mWidth/2 - (float) last.getX());
		float offsetY = Math.abs(mHeight/2 + (float) last.getY());
		
		float homeX = 0, homeY = 0;
		
		for (int i = 0; i < mPath.size() - 1; i++) {
			Location a = mPath.get(i);
			Location b = mPath.get(i + 1);
			
			float aX = (float) a.getX();
			float aY = (float) -a.getY();
			float bX = (float) b.getX();
			float bY = (float) -b.getY();
			
			aX = (aX > mWidth/2 ? aX - offsetX : aX + offsetX);
			bX = (bX > mWidth/2 ? bX - offsetX : bX + offsetX);
			
			aY = (aY > mHeight/2 ? aY - offsetY : aY + offsetY);
			bY = (bY > mHeight/2 ? bY - offsetY : bY + offsetY);
			
			if (i == 0) {
				homeX = aX;
				homeY = aY;
			}
			
			if (mReturnId > 0) {
				if (b.getId() < mReturnId)
					canvas.drawLine(aX, aY, bX, bY, mPathPaint);
				else 
					canvas.drawLine(aX, aY, bX, bY, mReturnPaint);
			} else {
				canvas.drawLine(aX, aY, bX, bY, mPathPaint);
			}
		}
		
		canvas.drawBitmap(mHome, homeX - mHome.getWidth()/2, homeY - mHome.getHeight()/2, null);
	}
	
	public boolean returnHome() {
		if (mPath.size() < 2)
			return false;
		
		mReturnId = mPath.get(mPath.size() - 1).getId();
		return true;
	}
	
}